import 'dart:async';
import 'dart:convert';
import 'package:dio/dio.dart';

class StreamApiService {
  final dio = Dio();
  final String apiUrl;
  final String apiKey;

  StreamApiService({
    required this.apiUrl,
    required this.apiKey,
  }) {
    // 配置dio实例
    dio.options.headers = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $apiKey',
    };
    dio.options.responseType = ResponseType.stream; // 设置响应类型为流
  }

  Stream<String> streamResponse(String prompt) async* {
    try {
      final response = await dio.post(
        apiUrl,
        data: {
          'model': 'gpt-3.5-turbo',
          'messages': [
            {'role': 'user', 'content': prompt}
          ],
          'stream': true,
        },
      );

      // 获取响应流
      final responseStream = response.data.stream;

      // 使用utf8解码器创建转换流
      final streamTransformer = StreamTransformer<List<int>, String>.fromHandlers(
        handleData: (data, sink) {
          final String chunk = utf8.decode(data);
          // 处理SSE格式的数据
          for (final line in chunk.split('\n')) {
            if (line.startsWith('data: ') && line != 'data: [DONE]') {
              try {
                final jsonStr = line.substring(6); // 移除 'data: ' 前缀
                final Map<String, dynamic> data = jsonDecode(jsonStr);
                final String? content = data['choices']?[0]?['delta']?['content'];
                if (content != null) {
                  sink.add(content);
                }
              } catch (e) {
                print('解析JSON失败: $e');
              }
            }
          }
        },
      );

      yield* responseStream.transform(streamTransformer);

    } catch (e) {
      yield* Stream.error('请求失败: $e');
    }
  }

  // 取消请求的方法
  void cancelRequest() {
    dio.close(force: true);
  }
}

// 使用示例
void main() async {
  final apiService = StreamApiService(
    apiUrl: 'https://api.openai.com/v1/chat/completions',
    apiKey: 'your-api-key',
  );

  // 创建取消令牌
  final cancelToken = CancelToken();

  try {
    final prompt = "请给我讲个故事";

    // 监听流式响应
    final subscription = apiService.streamResponse(prompt).listen(
          (content) {
        print(content); // 输出内容
      },
      onError: (error) {
        print('Error: $error');
      },
      onDone: () {
        print('\n响应完成');
      },
    );

    // 可以在需要时取消订阅
    // subscription.cancel();

  } catch (e) {
    print('Error: $e');
  }
}